package network.server;

import java.io.IOException;
import java.net.Socket;

import driver.PersonDriver;

import state.person.Person;
import system.GlobalData;

import network.managers.ObserverManager;
import network.server.SocketThread;

import messages.BaseMessage;
import messages.GeneralAck;
import messages.MessageFactory;
import messages.MessageType;
import messages.persondispatcher.CurrentPeopleStateMessage;
import messages.persondispatcher.PersonCreationMessage;

public class PersonDispatcherObserverHandler extends SocketThread {

    private boolean shouldContinue = true;

    public PersonDispatcherObserverHandler(ConnectionListenerThread parent, Socket sockToHandle)
    {
        super(parent, sockToHandle);
    }

    @Override
    public void runThread()
    {
        boolean hasReceivedRegistration = false;

        while (shouldContinue)
        {
            if (remoteSock.isClosed())
            {
                break;
            }

            BaseMessage message = null;

            try
            {
                message = MessageFactory.readMessage(remoteSock);
            }
            catch (IOException e)
            {
                // TODO: log
                continue;
            }
            
            if (message == null)
            {
                continue;
            }

            if (hasReceivedRegistration)
            {
                switch (message.getMessageType())
                {
                    case DeregistrationMessage:
                        shouldContinue = false;
                        break;
                    case CurrentPeopleStateRequest:

                        synchronized (GlobalData.state.activePeople)
                        {
                            synchronized (GlobalData.state.deactivatedPeople)
                            {
                                try
                                {
                                    CurrentPeopleStateMessage retMess = new CurrentPeopleStateMessage(GlobalData.state);

                                    remoteSock.getOutputStream().write(retMess.toByteArray());
                                }
                                catch (IOException e)
                                {
                                    // TODO: log
                                }
                            }
                        }
                        break;
                    case PersonCreationMessage:
                        PersonCreationMessage perMess = (PersonCreationMessage) message;
                        Person p = perMess.getPerson();
                        
                        if (p != null)
                        {
                            synchronized (GlobalData.state.activePeople)
                            {
                                GlobalData.state.activePeople.add(p);
                            }
                            
                            PersonDriver.getInstance().doCreation(p);
                        }
                        break;
                    default:
                        //NOOP
                        break;
                }
            }
            else
            {
                if (message.getMessageType() == MessageType.ObserverRegistrationMessage)
                {
                    GeneralAck ack = new GeneralAck(message.getMessageType(), true);

                    try
                    {
                        remoteSock.getOutputStream().write(ack.toByteArray());
                    }
                    catch (IOException e)
                    {
                        // TODO: log
                    }
                    
                    ObserverManager.getInstance().registerObserver(this);

                    hasReceivedRegistration = true;
                }
                else
                {
                    break;
                }
            }

        }
        
        if (hasReceivedRegistration)
        {
        	ObserverManager.getInstance().deregisterObserver(this);
        }
    }
}
